﻿using System;

using log4net;


namespace ExtensibleEventViewer.Console.Tasks
{
	internal abstract class TaskBase
	{
		public event Action<TaskBase> ExecutedSuccessfuly;

		private readonly ILog _log;

		protected TaskBase()
		{
			_log = LogManager.GetLogger(GetType());
		}

		public DateTime LastExecutionTime
		{
			get; 
			private set;
		}

		public DateTime ExecuteOn
		{
			get; 
			set;
		}

		public TimeSpan RescheduleInterval
		{
			get; 
			set;
		}

		public bool IsRescheduled
		{ 
			get; 
			set;
		}

		private volatile bool _executing;
		public bool Executing
		{
			get
			{
				return _executing;
			}
			private set
			{
				_executing = value;
			}
		}

		protected abstract void DoExecute();

		public void Execute(object state)
		{
			if(Executing)
			{
				return;
			}

			Executing = true;

			try
			{
				DoExecute();

				if (ExecutedSuccessfuly != null)
				{
					ExecutedSuccessfuly(this);
				}

				LastExecutionTime = DateTime.UtcNow;

				if (IsRescheduled && RescheduleInterval != TimeSpan.Zero)
				{
					ExecuteOn = LastExecutionTime.Add(RescheduleInterval);
				}
			}
			catch(Exception ex)
			{
				_log.Error("ThreadUnhandledException", ex);

				ExecuteOn = IsRescheduled && RescheduleInterval != TimeSpan.Zero
				            	?
				            		DateTime.UtcNow.Add(RescheduleInterval)
				            	:
				            		ExecuteOn.AddSeconds(2);
			}
			finally
			{
				Executing = false;
			}
		}
	}
}
